package com.open.capacity.reimburse.service.impl;

import com.open.capacity.model.system.LoginAppUser;
import com.open.capacity.model.system.SysUser;
import com.open.capacity.reimburse.constant.TrafficTypes;
import com.open.capacity.reimburse.service.*;
import com.open.capacity.reimburse.util.uuid.UUIDUtils;
import com.open.capacity.reimburse.dao.BillCarApply2CostDao;
import com.open.capacity.reimburse.dao.BillGoabroad2CostDao;
import com.open.capacity.reimburse.entity.BillCarApply2;
import com.open.capacity.reimburse.entity.BillCarApply2Cost;
import com.open.capacity.reimburse.entity.BillGoabroad2Cost;
import com.open.capacity.reimburse.exception.BusinessException;
import com.open.capacity.user.service.SysAreaService;
import com.open.capacity.user.service.SysUserRelationService;
import com.open.capacity.user.service.SysUserService;
import com.open.capacity.utils.StringUtil;
import com.open.capacity.utils.SysUserUtil;
import com.open.capacity.workflow.service.WFProcessinstanceService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.open.capacity.commons.PageResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.open.capacity.commons.CodeEnum;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections4.MapUtils;

import com.open.capacity.reimburse.entity.BillGoabroad2;
import com.open.capacity.reimburse.dao.BillGoabroad2Dao;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;


@Service
public class BillGoabroad2ServiceImpl implements BillGoabroad2Service {

    @Autowired
    private BillGoabroad2Dao billDao;

    @Autowired
    private BillGoabroad2CostDao costDao;

    @Autowired
    private StdHotelService stdHotelService;

    @Autowired
    private StdMealAllowanceService stdMealAllowanceService;

    @Autowired
    private StdTrafficAllowanceService stdTrafficAllowanceService;

    @Autowired
    private StdTrafficService stdTrafficService;


    @Autowired
    private SysUserService userService;

    @Autowired
    private SysAreaService areaService;

    @Autowired
    private SysUserRelationService relationService;

    @Autowired
    private WFProcessinstanceService processinstanceService;

    @Override
    public int verifyBill(BillGoabroad2 bill) {
        String errorMsg = verify(bill);
        if (StringUtils.isNotEmpty(errorMsg)) {
            throw new BusinessException(errorMsg);
        }
        return 1;
    }

    /**
     * 添加
     *
     * @param bill
     */
    @Transactional(rollbackFor = Exception.class)
    public int save(BillGoabroad2 bill, Integer force) {
        LoginAppUser loginUser = SysUserUtil.getLoginAppUser();

        if (force != 1) {
            //规则校验
            String errorMsg = verify(bill);
            if (StringUtils.isNotEmpty(errorMsg)) {
                throw new BusinessException(errorMsg);
            }
        }

        bill.setPostname(relationService.getPostNames(bill.getUserid()));
        bill.setStatus(1);
        bill.setCreateTime(new Date());
        bill.setCreateUserid(loginUser.getId());
        bill.setCreateUsername(loginUser.getRealName());
        bill.setDestinationStr(areaService.findByIds(bill.getDestination()));

        SysUser user = userService.findById(bill.getUserid());
        Assert.notNull(user, "找不到报销人信息");
        bill.setUsername(user.getRealName());

        BigDecimal cost = BigDecimal.ZERO;
        for (BillGoabroad2Cost item : bill.getCostList()) {
            item.setId(UUIDUtils.getOriginalUUIDWithoutBar());
            item.setRefId(bill.getId());
            if(item.getMoney()!=null) {
                cost = cost.add(item.getMoney());
            }
            costDao.save(item);
        }
        bill.setCost(cost);
        int count = billDao.save(bill);
        return count;
    }

    //数据校验
    public String verify(BillGoabroad2 bill) {
        String errorMsg = "";
        String userId = bill.getUserid();
        String destination = bill.getDestination();//目的地
        Date startTime = bill.getStartTime();//开始时间
        Date endTime = bill.getEndTime();//结束时间

        Map<String, List<BillGoabroad2Cost>> mapCost = bill.getCostList().stream().collect(Collectors.groupingBy(item -> item.getItemCode(), HashMap::new, Collectors.toList()));
        int personCounts = 1;
        for (Map.Entry entry_item : mapCost.entrySet()) {
            switch (entry_item.getKey().toString()) {
                case "1": //住宿费校验
                    errorMsg += stdHotelService.verify(userId, null, personCounts, destination, startTime, endTime, ((List<BillGoabroad2Cost>) entry_item.getValue()).stream().map(e -> e.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add));
                    break;
                case "2": //机票费
                    errorMsg += stdTrafficService.verify(userId, null, TrafficTypes.PLANE, ((List<BillGoabroad2Cost>) entry_item.getValue()).stream().map(e -> e.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add));
                    break;
                case "4": //伙食补贴校验
                    errorMsg += stdMealAllowanceService.verify(userId, null, personCounts, destination, startTime, endTime, ((List<BillGoabroad2Cost>) entry_item.getValue()).stream().map(e -> e.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add));
                    break;
                case "5": //市内交通补贴校验
                    errorMsg += stdTrafficAllowanceService.verify(userId, null, personCounts, destination, startTime, endTime, ((List<BillGoabroad2Cost>) entry_item.getValue()).stream().map(e -> e.getMoney()).reduce(BigDecimal.ZERO, BigDecimal::add));
                    break;
            }
        }

        return errorMsg;
    }

    /**
     * 修改
     *
     * @param bill
     */
    @Transactional(rollbackFor = Exception.class)
    public int update(BillGoabroad2 bill, Integer force) {
        LoginAppUser loginUser = SysUserUtil.getLoginAppUser();

        if (force != 1) {
            //规则校验
            String errorMsg = verify(bill);
            if (StringUtils.isNotEmpty(errorMsg)) {
                throw new BusinessException(errorMsg);
            }
        }

        bill.setPostname(relationService.getPostNames(bill.getUserid()));
        bill.setStatus(1);
        //bill.setCreateTime(new Date());
        //bill.setCreateUserid(loginUser.getId());
        //bill.setCreateUsername(loginUser.getRealName());
        bill.setDestinationStr(areaService.findByIds(bill.getDestination()));

        SysUser user = userService.findById(bill.getUserid());
        Assert.notNull(user, "找不到报销人信息");
        bill.setUsername(user.getRealName());

        BigDecimal cost = BigDecimal.ZERO;
        costDao.deleteByRefId(bill.getId());
        for (BillGoabroad2Cost item : bill.getCostList()) {
            item.setId(UUIDUtils.getOriginalUUIDWithoutBar());
            item.setRefId(bill.getId());
            if(item.getMoney()!=null) {
                cost = cost.add(item.getMoney());
            }
            costDao.save(item);
        }
        bill.setCost(cost);
        int count = billDao.update(bill);
        return count;
    }


    /**
     * 删除
     *
     * @param id
     */
    public int delete(String id) {
        return billDao.delete(id);
    }

    /**
     * 查询记录
     *
     * @param id
     * @return
     */
    public BillGoabroad2 findById(String id) {
        BillGoabroad2 bill = billDao.findById(id);
        if (bill != null) {
            bill.setCostList(costDao.findByRefId(id));
            bill.setProcessCode(processinstanceService.findById(id).getCode());
            bill.setDepartmentName(userService.findById(bill.getUserid()).getDepartmentName());

            BigDecimal resut = bill.getCost();
            Integer number9Count = resut.divide(BigDecimal.valueOf(1000000)).intValue();
            bill.setNumber9(number9Count);
            resut = resut.subtract(BigDecimal.valueOf(number9Count * 1000000));

            Integer number8Count = resut.divide(BigDecimal.valueOf(100000)).intValue();
            bill.setNumber8(number8Count);
            resut = resut.subtract(BigDecimal.valueOf(number8Count * 100000));

            Integer number7Count = resut.divide(BigDecimal.valueOf(10000)).intValue();
            bill.setNumber7(number7Count);
            resut = resut.subtract(BigDecimal.valueOf(number7Count * 10000));

            Integer number6Count = resut.divide(BigDecimal.valueOf(1000)).intValue();
            bill.setNumber6(number6Count);
            resut = resut.subtract(BigDecimal.valueOf(number6Count * 1000));

            Integer number5Count = resut.divide(BigDecimal.valueOf(100)).intValue();
            bill.setNumber5(number5Count);
            resut = resut.subtract(BigDecimal.valueOf(number5Count * 100));

            Integer number4Count = resut.divide(BigDecimal.valueOf(10)).intValue();
            bill.setNumber4(number4Count);
            resut = resut.subtract(BigDecimal.valueOf(number4Count * 10));

            Integer number3Count = resut.divide(BigDecimal.valueOf(1)).intValue();
            bill.setNumber3(number3Count);
            resut = resut.subtract(BigDecimal.valueOf(number3Count * 1));

            Integer number2Count = resut.divide(BigDecimal.valueOf(0.1)).intValue();
            bill.setNumber2(number2Count);
            resut = resut.subtract(BigDecimal.valueOf(number2Count * 0.1));

            Integer number1Count = resut.divide(BigDecimal.valueOf(0.01)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue();
            bill.setNumber1(number1Count);
        }
        return bill;
    }

    /**
     * 分页
     *
     * @param params
     * @return
     */
    public PageResult<BillGoabroad2> pageAll(Map<String, Object> params) {
        //设置分页信息，分别是当前页数和每页显示的总记录数【记住：必须在mapper接口中的方法执行之前设置该分页信息】
        if (MapUtils.getInteger(params, "page") != null && MapUtils.getInteger(params, "limit") != null)
            PageHelper.startPage(MapUtils.getInteger(params, "page"), MapUtils.getInteger(params, "limit"), true);

        List<BillGoabroad2> list = billDao.findAll(params);
        PageInfo<BillGoabroad2> pageInfo = new PageInfo(list);

        return PageResult.<BillGoabroad2>builder().data(pageInfo.getList()).resp_code(CodeEnum.SUCCESS.getCode()).count(pageInfo.getTotal()).build();
    }

    /**
     * 列表
     *
     * @param params
     * @return
     */
    public List<BillGoabroad2> findAll(Map<String, Object> params) {
        return billDao.findAll(params);
    }

}
